# -*- coding: UTF-8 -*-
import base64
import calendar
import hashlib
import json
import random
import time
from email.mime.text import MIMEText
from smtplib import SMTP_SSL

import requests
import urllib3
from Crypto import Random
from Crypto.Cipher import DES3
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
from Crypto.Util.Padding import pad

import config

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


# 加密字符串
def des_enc(string, key, iv):
    """
    加密字符串
    :param string: 要加密的字符串
    :param key: 密钥
    :param iv: 偏移量
    :return: 返回加密后的数据
    """
    cipher = DES3.new(key, DES3.MODE_CBC, iv.encode("utf-8"))
    ct_bytes = cipher.encrypt(pad(string.encode('utf8'), DES3.block_size))
    ct = base64.b64encode(ct_bytes).decode('utf8')
    return ct


# 创建公钥和密钥
def create_key():
    """
    创建公钥和密钥
    :return: 返回公钥[0]和密钥[1]
    """
    rsa = RSA.generate(1024, Random.new().read)
    private_key = str(rsa.export_key(), 'utf8').split('-\n')[1].split('\n-')[0]
    public_key = str(rsa.publickey().export_key(), 'utf8').split('-\n')[1].split('\n-')[0]
    config.publicKey = public_key
    config.privateKey = private_key
    return public_key, private_key


# 获取sessionId和appKey
def get_sa(public_key, private_key):
    """
    获取sessionId和appKey
    :param public_key: 公钥
    :param private_key: 私钥
    :return: session_id[0],app_key[1]
    """
    res = requests.post(
        "https://app.17wanxiao.com:443/campus/cam_iface46/exchangeSecretkey.action",
        headers={"User-Agent": "Dalvik/2.1.0 (Linux; U; Android 11; Redmi K20 Pro Build/RKQ1.200826.002)"},
        json={"key": public_key},
        verify=False
    )
    rsa_base64 = base64.b64decode(res.text.encode(res.apparent_encoding))
    cipher = PKCS1_v1_5.new(
        RSA.importKey("-----BEGIN RSA PRIVATE KEY-----\n" + private_key + "\n-----END RSA PRIVATE KEY-----"))
    rsa_dec = str(cipher.decrypt(rsa_base64, Random.new().read), 'utf-8')
    info = json.loads(rsa_dec)
    session_id = info["session"]
    app_key = info["key"][:24]
    config.sessionId = session_id
    config.appKey = app_key
    return session_id, app_key


# 账密登录
def login(session_id, app_key):
    """
    账密登录
    :param session_id: session_id
    :param app_key: app_key
    :return: 返回登录信息
    """
    pwd = []
    for i in config.password:
        pwd.append(des_enc(i, app_key, "66666666"))
    config.login_cf["password"] = pwd
    upload_args = {
        "session": session_id,
        "data": des_enc(json.dumps(config.login_cf), app_key, "66666666")
    }
    print(upload_args)
    res = requests.post(
        "https://app.17wanxiao.com/campus/cam_iface46/loginnew.action",
        headers={"campusSign": hashlib.sha256(json.dumps(upload_args).encode('utf-8')).hexdigest()},
        json=upload_args,
        verify=False
    ).json()
    return res


# 获取验证码
def get_sms():
    """
    获取验证码
    :return: 获取验证码信息
    """
    sms_data = des_enc(json.dumps(config.sms_cf), config.appKey, '66666666')
    sms_args = {
        'session': config.sessionId,
        'data': sms_data
    }
    res = requests.post(
        "https://app.59wanmei.com/campus/cam_iface46/gainMatrixCaptcha.action",
        headers={"campusSign": hashlib.sha256(json.dumps(sms_args).encode('utf-8')).hexdigest()},
        json=sms_args,
        verify=False
    )
    return res


# 验证码登录
def sms_login():
    """
    验证码登录
    :return: 验证码登录信息
    """
    code_data = des_enc(json.dumps(config.sms_login_cf), config.appKey, '66666666')
    code_args = {
        'session': config.sessionId,
        'data': code_data
    }
    res = requests.post(
        "https://app.59wanmei.com/campus/cam_iface46/registerUsersByTelAndLoginNew.action",
        headers={"campusSign": hashlib.sha256(json.dumps(code_args).encode('utf-8')).hexdigest()},
        json=code_args,
        verify=False
    )
    return res


# 获取用户信息
def get_user_info(token):
    """
    获取用户信息
    :param token: 用户密钥
    :return: 用户信息
    """
    user_data = {
        "appClassify": "DK",
        "token": token
    }
    sign_url = "https://reportedh5.17wanxiao.com/api/clock/school/getUserInfo"
    res = requests.post(sign_url, data=user_data)
    config.token = token
    config.clock_cf['jsonData']['token'] = token
    return res


# 设置打卡参数
def set_lock_in_cf(user):
    config.clock_cf['jsonData']['deptStr']['text'] = user['classDescription']
    config.clock_cf['jsonData']['deptStr']['deptid'] = user['classId']
    config.clock_cf['jsonData']['customerid'] = user['customerId']
    config.clock_cf['jsonData']['deptid'] = user['classId']
    config.clock_cf['jsonData']['stuNo'] = user['stuNo']
    config.clock_cf['jsonData']['username'] = user['username']
    config.clock_cf['jsonData']['userid'] = user['userId']

    arg = {
        "businessType": "epmpics",
        "jsonData": {
            "templateid": "pneumonia",
            "token": config.token
        },
        "method": "userComeApp"
    }

    res = requests.post('https://reportedh5.17wanxiao.com/sass/api/epmpics', json=arg, verify=False)
    data = json.loads(res.text)['data']
    config.clock_cf['jsonData']['areaStr'] = json.loads(data)['areaStr']


# 执行打卡操作
def clock_in():
    """
    执行打卡操作
    :return: 返回打卡是否成功
    """
    # 设置打卡时间为当前时间
    config.clock_cf['jsonData']['reportdate'] = calendar.timegm(time.gmtime())
    # 随机体温 36.1-36.6
    config.clock_cf['jsonData']['updatainfo'][0]['value'] = f'36.{random.randint(1, 6)}'
    res = requests.post('https://reportedh5.17wanxiao.com/sass/api/epmpics', json=config.clock_cf)
    print(res.text)
    return res


# 输出打卡成功
def writ_log():
    data = config.clock_cf
    addr = json.loads(data['jsonData']['areaStr'])
    log_addr = f'地址：{addr["text"].replace("-", "")}{addr["address"]}'
    log_name = f"姓名：{data['jsonData']['username']}"
    log_test = f"健康码：{data['jsonData']['updatainfo'][4]['value']}"
    log_temp = f"体温：{data['jsonData']['updatainfo'][0]['value']}"
    log_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    print(f'打卡成功!\n{log_name}\n{log_temp}\n{log_test}\n{log_addr}\n{log_time}')
    return f'打卡成功!\n{log_name}\n{log_temp}\n{log_test}\n{log_addr}\n{log_time}'


# 打卡状态发送到邮箱
def mail(message):
    """
    打卡状态发送到邮箱
    :param message: str 邮件内容
    :return:
    """
    # 邮件内容
    msg = MIMEText(message, 'plain', _charset="utf-8")
    # 邮件主题描述
    msg["Subject"] = '健康打卡提醒'
    with SMTP_SSL(host="smtp.qq.com", port=465) as smtp:
        # 登录发邮件服务器
        smtp.login(user=config.user, password=config.pwd)
        # 实际发送、接收邮件配置
        smtp.sendmail(from_addr=config.user, to_addrs=config.email.split(','), msg=msg.as_string())


# 主方法入口
def main_handler(event, context):
    # 获取公钥密钥
    key = create_key()
    public_key = key[0]
    private_key = key[1]

    # 获取sessionId和appKey
    sa = get_sa(public_key, private_key)
    session_id = sa[0]
    app_key = sa[1]

    res = login(session_id, app_key)
    print(res)
    if not res['result_']:
        sms_res = get_sms()
        print(sms_res.text)
        if json.loads(sms_res.text)['result_']:
            print('Please Input SMS Code:', end="")
            config.sms_login_cf['sms'] = input()
            sms_login_res = sms_login()
            if not json.loads(sms_login_res.text)['result_']:
                print('error')
        else:
            print('error')
    user_info = get_user_info(session_id)
    user = user_info.json()['userInfo']
    set_lock_in_cf(user)
    clock_res = clock_in()
    logs = "打卡失败"
    if int(json.loads(clock_res.text)['code']) == 10000:
        logs = writ_log()
    else:
        print("打卡出错")
    mail(logs)
